import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import io
import base64

from matplotlib import image as mpimg
from matplotlib.patches import Rectangle
from plottable import Table

from module_admin.entity.vo.data_vo import BillFileData


class ExportPdfService:
    @classmethod
    def export_and_get_base64(cls, bill_file_data: BillFileData):
        if bill_file_data is None:
            return
        # 5.51*9.44
        # 处理数据，换行+缩小字体
        rows = [
            [bill_file_data.department_name, '', bill_file_data.order_id],
            [bill_file_data.start_and_destination, '', bill_file_data.start_and_end_time],
            [bill_file_data.car_brand_and_car_type, '', bill_file_data.car_number],
            [bill_file_data.driver_name, '', bill_file_data.use_user],
            [bill_file_data.mileage, '', bill_file_data.dispatch_name],
            [bill_file_data.expenses],
            [bill_file_data.sign],
            [bill_file_data.export_time]
        ]
        # 创建画布和子图
        x_size = 240 / 25.4 / 10
        y_size = 140 / 25.4 / 10
        number = 23  # 10号 3.78英寸

        fig, ax = plt.subplots(figsize=(x_size * 10, y_size * 10), constrained_layout=True)
        plt.subplots_adjust(left=0, right=1, bottom=0, top=1, wspace=None, hspace=None)
        plt.rcParams['font.sans-serif'] = ['SimHei']  # 指定默认字体
        plt.rcParams['axes.unicode_minus'] = False  # 解决保存图像时负号'-'显示为方块的问题

        # 设置列宽和行高 140*240
        column_widths = [x_size * 0.4, x_size * 0.2, x_size * 0.4]  # 相对于子图宽度的比例 三行
        row_height = y_size / 8  # 相对于子图高度的比例 5列
        y_offset = y_size  # 初始y偏移量，用于调整表格位置
        # 绘制单元格和文本
        for i, row in enumerate(rows):
            y = y_offset - i * row_height
            if len(row) == 1:
                x = 0
                for column_width in column_widths:
                    x += column_width
                    # 绘制单元格（矩形）
                start_index = str(row[0]).find("static/")
                if start_index != -1:
                    img = mpimg.imread(str(row[0])[start_index:])
                    imgplot = ax.imshow(img, extent=[0, x, y - row_height, y], aspect='auto')
                rect = Rectangle(xy=(0, y - row_height), width=x, height=row_height,
                                 edgecolor='black', facecolor='none')
                ax.add_patch(rect)
                if start_index == -1:
                    # 在单元格中添加文本
                    ax.text((x / 2) / x_size, (y - row_height / 2) / y_size, cls.get_value2(str(row[0]), 10),
                            horizontalalignment='center',
                            verticalalignment='center',
                            transform=ax.transAxes,
                            fontsize=10)
            else:
                for j, value in enumerate(row):
                    x = 0
                    for jj in range(0, j):
                        x += column_widths[jj]
                    width = column_widths[j]
                    # 绘制单元格（矩形）
                    rect = Rectangle(xy=(x, y - row_height), width=width, height=row_height,
                                     edgecolor='black', facecolor='none')
                    ax.add_patch(rect)
                    # 在单元格中添加文本
                    ax.text((x + width / 2) / x_size, (y - row_height / 2) / y_size, cls.get_value2(str(value), 4),
                            horizontalalignment='center',
                            verticalalignment='center',
                            transform=ax.transAxes,
                            fontsize=10)
        ax.set_xlim(0, x_size)
        ax.set_ylim(0, y_size)
        ax.set_aspect('equal')
        # 隐藏坐标轴
        ax.axis('off')
        # 将图形保存到字节流中
        buf = io.BytesIO()
        plt.savefig(buf, format='pdf')
        buf.seek(0)

        # 将字节流转换为base64编码
        img_str = base64.b64encode(buf.read()).decode('utf-8')

        # 清理matplotlib以避免内存泄漏
        plt.close(fig)
        return img_str

    @classmethod
    def get_value(cls, s: str):
        num_segments = (len(s) + 22) // 23
        result = ""
        for i in range(num_segments):
            segment = s[i * 23:min((i + 1) * 23, len(s))]
            result += segment + "\n"
        if result.endswith("\n"):
            result = result[:-1]
        return result

    @classmethod
    def get_value2(cls, s: str, width: int):
        chinese_chars = set(chr(i) for i in range(0x4e00, 0x9fff))
        last_len = 0
        len = 0
        length = 0
        result = ""
        for char in s:
            if length >= 12 * width:
                segment = s[last_len: last_len + len]
                result += segment + "\n"
                last_len = last_len + len
                length = 0
                len = 0
            if char in chinese_chars:
                length += 2
                len += 1
            else:
                length += 1
                len += 1
        segment = s[last_len:]
        result += segment
        if result.endswith("\n"):
            result = result[:-1]
        return result
